package chen.yi.component.operate.log.config;

import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
/**
 * 用户名方法扫描器，负责加载和缓存@Username注解方法
 * 采用双重校验锁保证线程安全初始化
 * @author huat
 **/
public final class UsernameScanner {
    // 方法缓存（线程安全的ConcurrentHashMap）
    private static final ConcurrentMap<String, Method> CACHE =
            new ConcurrentHashMap<>();
    // 初始化状态标记
    private static volatile boolean initialized = false;
    private static final String FILE_NAME="META-INF/username-methods";

    /**
     * 扫描并初始化@Username方法
     * @throws Exception 当扫描过程出现异常时抛出
     */
    public static void scan() throws Exception {
        if(initialized) return;

        synchronized(UsernameScanner.class) {
            if(initialized) return;
            // 从classpath加载元数据文件
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            Enumeration<java.net.URL> urls = loader.getResources(FILE_NAME);

            if(!urls.hasMoreElements()) {
                throw new IllegalStateException("未加载到被@Username修饰的方法");
            }

            try(Scanner scanner = new Scanner(urls.nextElement().openStream())) {
                String line = scanner.nextLine();
                String[] parts = line.split("#");

                // 加载目标类和方法
                Class<?> clazz = Class.forName(parts[0]);
                Method method = clazz.getMethod(parts[1], HttpServletRequest.class);

                // 防止重复注册
                if(CACHE.putIfAbsent(clazz.getName(), method) != null) {
                    throw new IllegalStateException("重复的@Username方法");
                }

                // 初始化方法调用器
                MethodHolder.initialize(method, clazz.newInstance());
                initialized = true;
            }
        }
    }
}
